package com.siteseat.crudeq.kernel;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import com.siteseat.common.exception.InternalException;
import com.siteseat.common.foundation.Component;
import com.siteseat.common.foundation.PropertyHelper;
import com.siteseat.common.foundation.Rater;
import com.siteseat.common.misc.FileHelper;
import com.siteseat.common.misc.SizeUnit;
import com.siteseat.crudeq.common.raw.Constants;

public class QueueProfile extends Component implements Constants {

  private boolean      syncOnSave    = true;
  
  private String       name;

  private Integer      id;

  private int          chunkSizeByKB = DEFAULT_CHUNK_SIZE_BY_KB;

  private String       chunkFolderPath;

  private Rater        saveRater;

  private boolean      enable        = true;

  private boolean      checkChunk    = false;

  /**
   * Gets the checkChunk
   * 
   * @return the checkChunk
   */
  public boolean isCheckChunk() {
    return checkChunk;
  }

  /**
   * Sets the checkChunk
   * 
   * @param checkChunk
   *          the checkChunk to set
   */
  public void setCheckChunk( boolean checkChunk ) {
    this.checkChunk = checkChunk;
  }

  /**
   * Gets the syncOnSave
   * 
   * @return the syncOnSave
   */
  public boolean isSyncOnSave() {
    return syncOnSave;
  }

  /**
   * Sets the syncOnSave
   * 
   * @param syncOnSave
   *          the syncOnSave to set
   */
  public void setSyncOnSave( boolean syncOnSave ) {
    this.syncOnSave = syncOnSave;
  }

  /**
   * Gets the enable
   * 
   * @return the enable
   */
  public boolean isEnable() {
    return enable;
  }

  /**
   * Sets the enable
   * 
   * @param enable
   *          the enable to set
   */
  public void setEnable( boolean enable ) {
    this.enable = enable;
  }

  /**
   * Gets the saveRater
   * 
   * @return the saveRater
   */
  public Rater getSaveRater() {
    return saveRater;
  }

  /**
   * Sets the saveRater
   * 
   * @param saveRater
   *          the saveRater to set
   */
  public void setSaveRater( Rater saveRater ) {
    this.saveRater = saveRater;
  }

  /**
   * 
   */
  protected void initRaters() {
    if( getSaveRater() == null ) {
      setSaveRater( new Rater( SizeUnit.MB, TimeUnit.SECONDS, "Save Rater - " + this ) );
    }
  }

  /**
   * @throws IOException
   */
  protected void normalizeChunkFolderPath() throws IOException {
    String p = getChunkFolderPath();
    PropertyHelper.ensureNotEmpty( log, p, "chunkFolderPath" );

    File folder = new File( getChunkFolderPath() );
    if( folder.canRead() == false ) {
      throw new IOException( "Cannot read folder <" + p + ">" );
    }
    if( folder.canWrite() == false ) {
      throw new IOException( "Cannot write folder <" + p + ">" );
    }
    FileHelper.createFolderIfNotExists( folder );
    setChunkFolderPath( folder.getCanonicalPath() );
  }

  /**
   * 
   */
  protected void checkChunkSize() {
    int sizeByKB = getChunkSizeByKB();
    PropertyHelper.ensurePositive( log, sizeByKB, "chunkSizeByKB" );
    if( sizeByKB > MAX_CHUNK_SIZE_BY_KB ) {
      throw new InternalException( "<chunkSizeByKB> property must be <= " + MAX_CHUNK_SIZE_BY_KB );
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected void doInit() throws Exception {
    PropertyHelper.ensureNotBlank( log, getName(), "name" );

    checkChunkSize();

    PropertyHelper.ensureNotNegative( log, getId().intValue(), "queueId" );

    initRaters();

    normalizeChunkFolderPath();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected void doDestroy() throws Exception {
    log.info( getSaveRater().reportAll( "\n" ) );

    setCheckChunk( false );
  }

  /**
   * 
   *
   * @param name
   */
  public void setName( String name ) {
    this.name = name;
    setBeanName( name );
  }

  /**
   * 
   *
   * @return
   */
  public String getName() {
    return this.name;
  }
  
  /**
   * {@inheritDoc}
   */
  @Override
  public void setBeanName( String beanName ) {
    super.setBeanName( beanName + "*" + getId() );
  }

  /**
   * Gets the chunkFolderPath
   * 
   * @return the chunkFolderPath
   */
  public String getChunkFolderPath() {
    return chunkFolderPath;
  }

  /**
   * Sets the chunkFolderPath
   * 
   * @param chunkFolderPath
   *          the chunkFolderPath to set
   */
  public void setChunkFolderPath( String chunkFolderPath ) {
    this.chunkFolderPath = chunkFolderPath;
  }

  /**
   * Gets the chunkSizeByKB
   * 
   * @return the chunkSizeByKB
   */
  public int getChunkSizeByKB() {
    return chunkSizeByKB;
  }

  /**
   * Sets the chunkSizeByKB
   * 
   * @param chunkSizeByKB
   *          the chunkSizeByKB to set
   */
  public void setChunkSizeByKB( int chunkSizeByKB ) {
    this.chunkSizeByKB = chunkSizeByKB;
  }

  /**
   * Gets the chunkSizeByMB
   * 
   * @return the chunkSizeByMB
   */
  public int getChunkSizeByMB() {
    return getChunkSizeByKB() / 1024;
  }

  /**
   * Gets the
   * 
   * @return the
   */
  public int getChunkSizeByBytes() {
    return getChunkSizeByKB() * 1024;
  }

  /**
   * Sets the chunkSizeByMB
   * 
   * @param chunkSizeByMB
   *          the chunkSizeByMB to set
   */
  public void setChunkSizeByMB( int chunkSizeByMB ) {
    setChunkSizeByKB( chunkSizeByMB * 1024 );
  }

  /**
   * Gets the chunkSizeByGB
   * 
   * @return the chunkSizeByGB
   */
  public int getChunkSizeByGB() {
    return getChunkSizeByMB() / 1024;
  }

  /**
   * Sets the chunkSizeByGB
   * 
   * @param chunkSizeByGB
   *          the chunkSizeByGB to set
   */
  public void setChunkSizeByGB( int chunkSizeByGB ) {
    setChunkSizeByMB( chunkSizeByGB * 1024 );
  }

  /**
   * Gets the id
   * 
   * @return the id
   */
  public Integer getId() {
    return id;
  }

  /**
   * Sets the id
   * 
   * @param id
   *          the id to set
   */
  public void setId( int id ) {
    this.id = Integer.valueOf( id );
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public String toString() {
    return "name=" + getName() + ", id=" + getId() + ", chunkFolderPath=" + getChunkFolderPath();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public boolean equals( Object obj ) {
    QueueProfile that;
    try {
      that = (QueueProfile)obj;
    } catch( ClassCastException e ) {
      return false;
    }
    return getId().equals( that.getId() );
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public int hashCode() {
    return getId().intValue();
  }

}
